﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace Web.Ajax.Logging
{
	public class RequestModule : IHttpModule
	{
		DateTime startTime;
		//public string Response="";

		//	--Planned change to avoid any cross pollinated responses
		private static string ResponseKey = "HttpResponseString";
		public void AppendResponse(string r)
		{
			var res = GetResponse();
			if (string.IsNullOrEmpty(res))
				res = "";
			res += r;
			HttpContext.Current.Items[ResponseKey] = res;
		}
		public string GetResponse()
		{
			var res = (string)HttpContext.Current.Items[ResponseKey];
			return res;
		}


		public void Init(HttpApplication app)
		{
			// register for events created by the pipeline
			app.BeginRequest += new EventHandler(this.OnBeginRequest);
			app.EndRequest += new EventHandler(this.OnEndRequest);
			app.Error += new EventHandler(this.OnError);
		}

		public void Dispose() { }

		public void OnBeginRequest(object o, EventArgs args)
		{
			try
			{
				var ep = Configuration.Logs.Current.GetEndpoint();
				if (ep == null || ep.Roll != Roll.Request)
					return;

				startTime = DateTime.Now;
				var app = (HttpApplication)o;
				var c = app.Context;
				var req = c.Request;
				if (string.IsNullOrEmpty(req.HttpMethod) || req.HttpMethod.ToLower().Trim() != "post")
					return;

				var rd = new StringBuilder(@"
<RequestDetails>
	<Ip>#ip#</Ip>
	<Domain>#dn#</Domain>
	<Agent>#ag#</Agent>
	<Url>#url#</Url>
</RequestDetails>");
				rd.Replace("#ip#", req.UserHostAddress);
				rd.Replace("#dn#", req.UserHostName);
				rd.Replace("#ag#", req.UserAgent);
				rd.Replace("#url#", req.RawUrl);
				Log.Info("--REQUEST DETAILS--", null, rd.ToString());


				var pos = req.InputStream.Position;
				var sr = new System.IO.StreamReader(req.InputStream);
				int length = (int)req.InputStream.Length;
				byte[] bytes = new byte[length];
				req.InputStream.Read(bytes, 0, length);
				var r = Encoding.UTF8.GetString(bytes);
				req.InputStream.Position = pos;
				Log.Info("--REQUEST BODY--", null, r);
				//Response = "";
				c.Response.Filter = new ResponseFiler(c.Response.Filter, this);
			}
			catch { }
		}
		public void OnEndRequest(object o, EventArgs args)
		{
			try
			{
				var ep = Configuration.Logs.Current.GetEndpoint();
				if (ep == null || ep.Roll != Roll.Request)
					return;

				TimeSpan elapsedtime = DateTime.Now - startTime;
				var app = (HttpApplication)o;
				var c = app.Context;

				if (string.IsNullOrEmpty(c.Request.HttpMethod) || c.Request.HttpMethod.ToLower().Trim() != "post")
					return;

				var response = GetResponse();
				Log.Info("--RESPONSE BODY--", null, response);
				Log.Info("--TIME TAKEN ("+elapsedtime.TotalSeconds.ToString()+" seconds) --", null, null);
			}
			catch { }
		}

		public void OnError(object o, EventArgs args)
		{
			try
			{
				var app = (HttpApplication)o;
				Log.Error(app.Server.GetLastError());
			}
			catch { }
		}

		public class ResponseFiler : System.IO.MemoryStream
		{
			public RequestModule RequestModule;
			private System.IO.Stream OutputStream;

			public ResponseFiler(System.IO.Stream OutputStream, RequestModule RequestModule)
			{
				this.OutputStream = OutputStream;
				this.RequestModule = RequestModule;
			}

			public override void Write(byte[] buffer, int offset, int count)
			{
				var s = UTF8Encoding.UTF8.GetString(buffer);
				if (RequestModule != null)
				{
					//RequestModule.Response += s;
					RequestModule.AppendResponse(s);
				}
				if(OutputStream!=null)
					OutputStream.Write(buffer, offset, count);
			}
		}
	}
}
